package com.ys.nms.module.business.libreApi.devices;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ys.nms.framework.common.util.http.HttpUtils;
import com.ys.nms.module.business.libreApi.config.LibreNmsConfig;
import com.ys.nms.module.business.libreApi.config.LibreNmsConfigFactory;
import com.ys.nms.module.business.libreApi.devices.req.DeviceAddRequest;
import com.ys.nms.module.business.libreApi.devices.req.DeviceUpdateRequest;
import com.ys.nms.module.business.libreApi.devices.req.LibreNmsDevice;
import com.ys.nms.module.business.libreApi.devices.resp.LibreNmsResponse;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class LibreNmsDeviceClient {

    private final LibreNmsConfigFactory configFactory;
    private final OkHttpClient httpClient;

    private static final String DEVICES_ENDPOINT = "/api/v0/devices";
    private static final String DEVICE_ENDPOINT = "/api/v0/devices/";

    private static final MediaType JSON = MediaType.get("application/json");

    // 构造函数：Spring 会自动注入 LibreNmsConfigFactory
    public LibreNmsDeviceClient(LibreNmsConfigFactory configFactory) {
        this.configFactory = configFactory;
        this.httpClient = new OkHttpClient.Builder()
                .callTimeout(Duration.ofSeconds(30))
                .connectTimeout(Duration.ofSeconds(10))
                .readTimeout(Duration.ofSeconds(30))
                .writeTimeout(Duration.ofSeconds(30))
                .build();
    }

    /**
     * 获取当前配置（根据激活的 profile）
     */
    private LibreNmsConfig getConfig() {
        return configFactory.getConfig();
    }

    /**
     * 获取请求头
     */
    private Map<String, String> getHeaders() {
        LibreNmsConfig config = getConfig();
        Map<String, String> headers = new HashMap<>();
        headers.put("X-Auth-Token", config.getToken());
        headers.put("Content-Type", "application/json");
        return headers;
    }

    /**
     * 构建完整的 API URL
     */
    public String buildUrl(String endpoint) {
        LibreNmsConfig config = getConfig();
        System.out.println("当前配置：" + config.toString());

        if (!config.getEnabled()) {
            throw new RuntimeException("LibreNMS客户端未启用，当前profile: " + configFactory.getActiveProfile());
        }
        if (StrUtil.isBlank(config.getBaseUrl())) {
            throw new RuntimeException("LibreNMS baseUrl未配置，当前profile: " + configFactory.getActiveProfile());
        }
        if (StrUtil.isBlank(config.getToken())) {
            throw new RuntimeException("LibreNMS apiToken未配置，当前profile: " + configFactory.getActiveProfile());
        }

        return config.getBaseUrl() + endpoint;
    }

    /**
     * 获取所有设备
     */
    public LibreNmsResponse<LibreNmsDevice> listDevices() {
        try {
            log.debug("获取设备列表，使用profile: {}", configFactory.getActiveProfile());
            String url = buildUrl(DEVICES_ENDPOINT);
            String response = HttpUtils.get(url, getHeaders());
            return JSONUtil.toBean(response, LibreNmsResponse.class);
        } catch (Exception e) {
            log.error("获取设备列表失败，profile: {}", configFactory.getActiveProfile(), e);
            throw new RuntimeException("获取设备列表失败: " + e.getMessage());
        }
    }

    /**
     * 根据主机名获取设备
     */
    public LibreNmsResponse<LibreNmsDevice> getDeviceByHostname(String hostname) {
        try {
            log.debug("获取设备: {}，使用profile: {}", hostname, configFactory.getActiveProfile());
            String url = buildUrl(DEVICES_ENDPOINT + "/" + hostname);
            String response = HttpUtils.get(url, getHeaders());

            // 调试：检查 snmpver 字段是否存在
            JSONObject jsonObject = JSONUtil.parseObj(response);
            JSONArray devices = jsonObject.getJSONArray("devices");
            if (devices != null && devices.size() > 0) {
                JSONObject firstDevice = devices.getJSONObject(0);
                System.out.println("snmpver字段值: " + firstDevice.getStr("snmpver"));
                System.out.println("所有字段: " + firstDevice.keySet());
            }

            LibreNmsResponse<LibreNmsDevice> result = JSONUtil.toBean(response,
                    new TypeReference<LibreNmsResponse<LibreNmsDevice>>() {}, true);

            if (result.getDevices() != null && !result.getDevices().isEmpty()) {
                System.out.println("解析后SNMP版本: " + result.getDevices().getFirst().getSnmpver());
            }

            return result;
        } catch (Exception e) {
            log.error("获取设备失败: {}, profile: {}", hostname, configFactory.getActiveProfile(), e);
            throw new RuntimeException("获取设备失败: " + e.getMessage());
        }
    }

    /**
     * 更新设备的一个或多个字段（使用统一的 OkHttpClient）
     */
    /**
     * 更新设备的一个或多个字段（使用统一的 OkHttpClient）
     */
    public LibreNmsResponse<Void> updateDeviceFields(String hostname, DeviceUpdateRequest request) {
        try {
            String url = buildUrl(DEVICE_ENDPOINT + hostname);
            String requestBody = JSONUtil.toJsonStr(request);
            RequestBody body = RequestBody.create(requestBody, JSON);

            Request.Builder requestBuilder = new Request.Builder()
                    .url(url)
                    .patch(body);

            // 手动添加所有 headers
            Map<String, String> headers = getHeaders();
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                requestBuilder.addHeader(entry.getKey(), entry.getValue());
            }

            Request okHttpRequest = requestBuilder.build();

            try (Response response = httpClient.newCall(okHttpRequest).execute()) {
                if (!response.isSuccessful()) {
                    String msg = "更新设备字段失败: HTTP " + response.code() + ", message: " + response.message();
                    log.error(msg);
                    throw new IOException(msg);
                }

                String responseBodyString = response.body() != null ? response.body().string() : "";
                log.debug("更新设备响应: {}", responseBodyString);

                return JSONUtil.toBean(responseBodyString, LibreNmsResponse.class);
            }
        } catch (Exception e) {
            log.error("更新设备字段失败: {}, profile: {}", hostname, configFactory.getActiveProfile(), e);
            throw new RuntimeException("更新设备字段失败: " + e.getMessage(), e);
        }
    }
    /**
     * 添加设备
     */
    public LibreNmsResponse<LibreNmsDevice> addDevice(DeviceAddRequest request) {
        try {
            log.debug("添加设备: {}，使用profile: {}", request.getHostname(), configFactory.getActiveProfile());
            String url = buildUrl(DEVICES_ENDPOINT);
            String requestBody = JSONUtil.toJsonStr(request);
            String response = HttpUtils.post(url, getHeaders(), requestBody);
            return JSONUtil.toBean(response, LibreNmsResponse.class);
        } catch (Exception e) {
            log.error("添加设备失败: {}, profile: {}", request.getHostname(), configFactory.getActiveProfile(), e);
            throw new RuntimeException("添加设备失败: " + e.getMessage());
        }
    }

    /**
     * 删除设备
     * @param hostname 设备主机名或 IP
     * @return 响应对象
     */
    /**
     * 删除设备
     * @param hostname 设备主机名或 IP
     * @return 响应对象
     */
    public LibreNmsResponse<Void> deleteDevice(String hostname) {
        try {
            log.debug("开始删除设备: {}, 使用 profile: {}", hostname, configFactory.getActiveProfile());
            String url = buildUrl(DEVICE_ENDPOINT + hostname);

            Request.Builder requestBuilder = new Request.Builder()
                    .url(url)
                    .delete();

            // 添加请求头
            Map<String, String> headers = getHeaders();
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                requestBuilder.addHeader(entry.getKey(), entry.getValue());
            }

            Request request = requestBuilder.build();

            try (Response response = httpClient.newCall(request).execute()) {
                if (!response.isSuccessful()) {
                    String msg = "删除设备失败: HTTP " + response.code() + ", message: " + response.message();
                    log.error(msg);
                    throw new IOException(msg);
                }

                String responseBodyString = response.body() != null ? response.body().string() : "{}";
                log.debug("删除设备响应: {}", responseBodyString);

                return JSONUtil.toBean(responseBodyString, LibreNmsResponse.class);
            }
        } catch (Exception e) {
            log.error("删除设备失败: {}, profile: {}", hostname, configFactory.getActiveProfile(), e);
            throw new RuntimeException("删除设备失败: " + e.getMessage(), e);
        }
    }
    /**
     * 获取当前使用的配置信息（用于调试）
     */
    public Map<String, Object> getCurrentConfigInfo() {
        LibreNmsConfig config = getConfig();
        Map<String, Object> info = new HashMap<>();
        info.put("profile", configFactory.getActiveProfile());
        info.put("baseUrl", config.getBaseUrl());
        info.put("apiToken", config.getToken());
        info.put("enabled", config.getEnabled());
        info.put("timeout", config.getTimeout());
        return info;
    }

    private Request.Builder addHeadersToRequest(Request.Builder builder, Map<String, String> headers) {
        for (Map.Entry<String, String> header : headers.entrySet()) {
            builder.addHeader(header.getKey(), header.getValue());
        }
        return builder;
    }

    /**
     * 检查当前配置是否有效
     */
    public boolean isConfigValid() {
        try {
            LibreNmsConfig config = getConfig();
            return config.getEnabled() &&
                    StrUtil.isNotBlank(config.getBaseUrl()) &&
                    StrUtil.isNotBlank(config.getToken());
        } catch (Exception e) {
            return false;
        }
    }


    //获取当前环境的url
    public String getCurrentUrl() {
        LibreNmsConfig config = getConfig();
        String baseUrl = config.getBaseUrl();
        return baseUrl;
    }
}